﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Emit.Study
{
    public class ProxyDemo
    {
        public void Execute()
        {
            // 创建被代理的类
            Type originalType = typeof(OriginalClass);

            // 创建动态程序集和模块
            AssemblyName assemblyName = new AssemblyName("DynamicAssembly");
            AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndCollect);
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");//, "DynamicModule.dll"

            // 创建代理类
            TypeBuilder typeBuilder = moduleBuilder.DefineType("ProxyClass", TypeAttributes.Public | TypeAttributes.Class, originalType);

            // 实现被代理类的方法
            foreach (var methodInfo in originalType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
            {
                var parameters = methodInfo.GetParameters().Select(p => p.ParameterType).ToArray();

                // 定义代理方法
                MethodBuilder methodBuilder = typeBuilder.DefineMethod(methodInfo.Name,
                    MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Final,
                    methodInfo.ReturnType,
                    parameters);

                // 实现代理方法的IL代码
                ILGenerator ilGenerator = methodBuilder.GetILGenerator();
                ilGenerator.Emit(OpCodes.Ldarg_1); // 加载参数 str
                ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); // 打印参数 str
                ilGenerator.Emit(OpCodes.Ldarg_0); // 加载this对象
                for (int i = 0; i < parameters.Length; i++)
                {
                    ilGenerator.Emit(OpCodes.Ldarg, i + 1); // 加载方法参数
                }
                ilGenerator.Emit(OpCodes.Call, typeof(OriginalClass).GetMethod(methodInfo.Name)); // 调用原始类的方法
                ilGenerator.Emit(OpCodes.Ret); // 返回

                // 绑定代理方法
                typeBuilder.DefineMethodOverride(methodBuilder, methodInfo);
            }

            // 创建代理类
            Type proxyType = typeBuilder.CreateType();

            // 保存动态程序集到文件
            moduleBuilder.CreateGlobalFunctions();

            // 创建代理对象
            object originalObject = new OriginalClass();
            object proxyObject = Activator.CreateInstance(proxyType);

            // 调用代理对象的方法
            ((OriginalClass)proxyObject).DoSomething("Hello, world!");
        }
    }


    public class ProxyBuilder
    {
        public static T CreateProxy<T>(Action<MethodInfo, Action<object, object[]>> interceptor)
        {
            var interfaceType = typeof(T);
            var assemblyName = new AssemblyName("DynamicProxyAssembly");
            var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
            var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
            var typeBuilder = moduleBuilder.DefineType(
                $"{interfaceType.Name}_Proxy",
                TypeAttributes.Public,
                typeof(object),
                new Type[] { interfaceType });

            // 为接口中的每个方法创建代理方法
            foreach (var methodInfo in interfaceType.GetMethods())
            {
                var methodBuilder = typeBuilder.DefineMethod(
                    $"{methodInfo.Name}_Proxy",
                    MethodAttributes.Public | MethodAttributes.Virtual,
                    CallingConventions.HasThis,
                    methodInfo.ReturnType,
                    Type.EmptyTypes);

                // 调用方法前的拦截逻辑
                interceptor(methodInfo, (target, args) =>
                {
                    Console.WriteLine(target);
                    // 调用真实方法的逻辑
                    //methodInfo.Invoke(target, args);
                    // 可以在这里添加额外的逻辑

                });

                // 创建代理方法的IL代码
                var il = methodBuilder.GetILGenerator();
                // 在这里编写调用真实方法和拦截逻辑的IL代码
            }

            var type = typeBuilder.CreateType();
            return (T)Activator.CreateInstance(type);
        }
    }

    // 使用示例
    public interface IExampleInterface
    {
        void DoSomething();
    }


}
